package xyz.yuzegod.megawalls.stats;

import com.google.gson.Gson;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import xyz.yuzegod.megawalls.MegaWalls;
import xyz.yuzegod.megawalls.classes.Classes;
import xyz.yuzegod.megawalls.classes.ClassesManager;
import xyz.yuzegod.megawalls.classes.ClassesType;
import xyz.yuzegod.megawalls.database.DataBase;
import xyz.yuzegod.megawalls.database.KeyValue;
import xyz.yuzegod.megawalls.game.Game;
import xyz.yuzegod.megawalls.game.GamePlayer;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class PlayerStats
{
    private static Map<GamePlayer, PlayerStats> statsMap;
    private static DataBase database;
    private static Game game;
    private static Gson gson;
    private GamePlayer gamePlayer;
    private int kills;
    private int finalKills;
    private int wins;
    private int games;
    private int coins;
    private int mythicDust;
    private String selected;
    private EffectStatsContainer effectStats;
    private Map<Classes, KitStatsContainer> kitStatsMap;
    private Classes cacheSelected;
    
    public PlayerStats(final GamePlayer gamePlayer) {
        this.kitStatsMap = new HashMap<Classes, KitStatsContainer>();
        this.gamePlayer = gamePlayer;
        if (!PlayerStats.database.isValueExists("megawalls_stats", SQLSettings.KV_STATS, new KeyValue("uuid", gamePlayer.getUuid().toString()))) {
            PlayerStats.database.dbInsert("megawalls_stats", new KeyValue("uuid", gamePlayer.getUuid().toString()).add("realname", gamePlayer.getName()).add("kills", 0).add("finalKills", 0).add("wins", 0).add("games", 0).add("coins", 5000).add("mythicDust", 0).add("selected", "HIM"));
            PlayerStats.database.dbInsert("megawalls_effects", new KeyValue("uuid", gamePlayer.getUuid().toString()).add("realname", gamePlayer.getName()).add("hologramEffect", "Default").add("killMessage", "Default").add("redColor", "RED").add("greenColor", "GREEN").add("blueColor", "BLUE").add("yellowColor", "YELLOW").add("enablePrefix", "true").add("enableItalic", "false").add("enableBold", "false").add("surface", "false"));
            for (final Classes classes : ClassesManager.getClasses()) {
                PlayerStats.database.dbInsert("classes_" + classes.getName(), new KeyValue("uuid", gamePlayer.getUuid().toString()).add("realname", gamePlayer.getName()).add("level", (int)((classes.getClassesType() == ClassesType.NOVICE) ? 1 : 0)).add("equipLevel", (classes.getClassesType() == ClassesType.NOVICE) ? 5 : 1).add("skillLevel", (classes.getClassesType() == ClassesType.NOVICE) ? 5 : 1).add("skill2Level", 1).add("skill3Level", 1).add("skill4Level", 1).add("wins", 0).add("games", 0).add("finalKills", 0).add("finalAssists", 0).add("enderChest", 3).add("masterPoints", 0).add("enableGoldTag", "false").add("playTime", 0).add("inventory", "null"));
            }
        }
    }
    
    public static PlayerStats get(final GamePlayer gamePlayer) {
        if (PlayerStats.statsMap.containsKey(gamePlayer)) {
            return PlayerStats.statsMap.get(gamePlayer);
        }
        final PlayerStats ps = new PlayerStats(gamePlayer);
        PlayerStats.statsMap.put(gamePlayer, ps);
        return PlayerStats.statsMap.get(gamePlayer);
    }
    
    public static void remove(final GamePlayer gamePlayer) {
        if (!PlayerStats.statsMap.containsKey(gamePlayer)) {
            return;
        }
        PlayerStats.statsMap.remove(gamePlayer);
    }
    
    public void update() {
        for (final KeyValue kv : PlayerStats.database.dbSelect("megawalls_stats", SQLSettings.KV_STATS, new KeyValue("uuid", this.gamePlayer.getUuid().toString()))) {
            this.kills = Integer.parseInt(kv.getString("kills"));
            this.finalKills = Integer.parseInt(kv.getString("finalKills"));
            this.wins = Integer.parseInt(kv.getString("wins"));
            this.games = Integer.parseInt(kv.getString("games"));
            this.coins = Integer.parseInt(kv.getString("coins"));
            this.mythicDust = Integer.parseInt(kv.getString("mythicDust"));
            this.selected = kv.getString("selected");
        }
        for (final KeyValue kv : PlayerStats.database.dbSelect("megawalls_effects", SQLSettings.KV_EFFECTS, new KeyValue("uuid", this.gamePlayer.getUuid().toString()))) {
            (this.effectStats = new EffectStatsContainer(this.gamePlayer)).setHologramEffect(kv.getString("hologramEffect"));
            this.effectStats.setKillMessage(kv.getString("killMessage"));
            this.effectStats.setRedColor(kv.getString("redColor"));
            this.effectStats.setGreenColor(kv.getString("greenColor"));
            this.effectStats.setBlueColor(kv.getString("blueColor"));
            this.effectStats.setYellowColor(kv.getString("yellowColor"));
            this.effectStats.setEnablePrefix(Boolean.parseBoolean(kv.getString("enablePrefix")));
            this.effectStats.setEnableItalic(Boolean.parseBoolean(kv.getString("enableItalic")));
            this.effectStats.setEnableBold(Boolean.parseBoolean(kv.getString("enableBold")));
            this.effectStats.setSurface(Boolean.parseBoolean(kv.getString("surface")));
        }
        for (final Classes classes : ClassesManager.getClasses()) {
            for (final KeyValue kv2 : PlayerStats.database.dbSelect("classes_" + classes.getName(), SQLSettings.KV_CLASSES, new KeyValue("uuid", this.gamePlayer.getUuid().toString()))) {
                final KitStatsContainer kitStats = new KitStatsContainer(this.gamePlayer, classes);
                kitStats.setLevel(Integer.parseInt(kv2.getString("level")));
                kitStats.setEquipLevel(Integer.parseInt(kv2.getString("equipLevel")));
                kitStats.setSkillLevel(Integer.parseInt(kv2.getString("skillLevel")));
                kitStats.setSkill2Level(Integer.parseInt(kv2.getString("skill2Level")));
                kitStats.setSkill3Level(Integer.parseInt(kv2.getString("skill3Level")));
                kitStats.setSkill4Level(Integer.parseInt(kv2.getString("skill4Level")));
                kitStats.setWins(Integer.parseInt(kv2.getString("wins")));
                kitStats.setGames(Integer.parseInt(kv2.getString("games")));
                kitStats.setFinalKills(Integer.parseInt(kv2.getString("finalKills")));
                kitStats.setFinalAssists(Integer.parseInt(kv2.getString("finalAssists")));
                kitStats.setEnderChest(Integer.parseInt(kv2.getString("enderChest")));
                kitStats.setMasterPoints(Integer.parseInt(kv2.getString("masterPoints")));
                kitStats.setEnableGoldTag(Boolean.parseBoolean(kv2.getString("enableGoldTag")));
                kitStats.setPlayTime(Long.parseLong(kv2.getString("playTime")));
                final String inventory = kv2.getString("inventory");
                if (!inventory.equalsIgnoreCase("null") && !inventory.equalsIgnoreCase("")) {
                    kitStats.setInventory((JsonObject)PlayerStats.gson.fromJson(inventory, (Class)JsonObject.class));
                }
                this.kitStatsMap.put(classes, kitStats);
            }
        }
        for (final Classes classes : ClassesManager.getClasses()) {
            if (!this.kitStatsMap.containsKey(classes)) {
                PlayerStats.database.dbInsert("classes_" + classes.getName(), new KeyValue("uuid", this.gamePlayer.getUuid().toString()).add("realname", this.gamePlayer.getName()).add("level", (int)((classes.getClassesType() == ClassesType.NOVICE) ? 1 : 0)).add("equipLevel", (classes.getClassesType() == ClassesType.NOVICE) ? 5 : 1).add("skillLevel", (classes.getClassesType() == ClassesType.NOVICE) ? 5 : 1).add("skill2Level", 1).add("skill3Level", 1).add("skill4Level", 1).add("wins", 0).add("games", 0).add("finalKills", 0).add("finalAssists", 0).add("enderChest", 3).add("masterPoints", 0).add("enableGoldTag", "false").add("playTime", 0).add("inventory", "null"));
            }
            for (final KeyValue kv2 : PlayerStats.database.dbSelect("classes_" + classes.getName(), SQLSettings.KV_CLASSES, new KeyValue("uuid", this.gamePlayer.getUuid().toString()))) {
                final KitStatsContainer kitStats = new KitStatsContainer(this.gamePlayer, classes);
                kitStats.setLevel(Integer.parseInt(kv2.getString("level")));
                kitStats.setEquipLevel(Integer.parseInt(kv2.getString("equipLevel")));
                kitStats.setSkillLevel(Integer.parseInt(kv2.getString("skillLevel")));
                kitStats.setSkill2Level(Integer.parseInt(kv2.getString("skill2Level")));
                kitStats.setSkill3Level(Integer.parseInt(kv2.getString("skill3Level")));
                kitStats.setSkill4Level(Integer.parseInt(kv2.getString("skill4Level")));
                kitStats.setWins(Integer.parseInt(kv2.getString("wins")));
                kitStats.setGames(Integer.parseInt(kv2.getString("games")));
                kitStats.setFinalKills(Integer.parseInt(kv2.getString("finalKills")));
                kitStats.setFinalAssists(Integer.parseInt(kv2.getString("finalAssists")));
                kitStats.setEnderChest(Integer.parseInt(kv2.getString("enderChest")));
                kitStats.setMasterPoints(Integer.parseInt(kv2.getString("masterPoints")));
                kitStats.setEnableGoldTag(Boolean.parseBoolean(kv2.getString("enableGoldTag")));
                kitStats.setPlayTime(Long.parseLong(kv2.getString("playTime")));
                final String inventory = kv2.getString("inventory");
                if (!inventory.equalsIgnoreCase("null") && !inventory.equalsIgnoreCase("")) {
                    kitStats.setInventory((JsonObject)PlayerStats.gson.fromJson(inventory, (Class)JsonObject.class));
                }
                this.kitStatsMap.put(classes, kitStats);
            }
        }
    }
    
    public Classes getSelected() {
        return ClassesManager.getClassesByName(this.selected);
    }
    
    public void setSelected(final String classesName) {
        if (ClassesManager.getClassesByName(classesName) == null) {
            return;
        }
        PlayerStats.database.dbUpdate("megawalls_stats", new KeyValue("Selected", classesName), new KeyValue("uuid", this.gamePlayer.getUuid().toString()));
        this.selected = classesName;
    }
    
    public void addKills(final int amount) {
        this.kills += amount;
        PlayerStats.database.dbUpdate("megawalls_stats", new KeyValue("kills", this.kills), new KeyValue("uuid", this.gamePlayer.getUuid().toString()));
    }
    
    public void addFinalKills(final int amount) {
        this.finalKills += amount;
        PlayerStats.database.dbUpdate("megawalls_stats", new KeyValue("finalKills", this.finalKills), new KeyValue("uuid", this.gamePlayer.getUuid().toString()));
    }
    
    public void addWins() {
        ++this.wins;
        PlayerStats.database.dbUpdate("megawalls_stats", new KeyValue("wins", this.wins), new KeyValue("uuid", this.gamePlayer.getUuid().toString()));
    }
    
    public void addGames() {
        ++this.games;
        PlayerStats.database.dbUpdate("megawalls_stats", new KeyValue("games", this.games), new KeyValue("uuid", this.gamePlayer.getUuid().toString()));
    }
    
    public void giveCoins(final CurrencyPackage currencyPackage) {
        if (MegaWalls.isActiveMode()) {
            currencyPackage.booster(1.0, "§6活动模式");
        }
        final int amount = currencyPackage.getCurrency();
        this.gamePlayer.sendMessage("§6+" + amount + "硬币 " + currencyPackage.getTip());
        this.coins += amount;
        PlayerStats.database.dbUpdate("megawalls_stats", new KeyValue("coins", this.coins), new KeyValue("uuid", this.gamePlayer.getUuid().toString()));
    }
    
    public void giveCoins(final int amount) {
        this.coins += amount;
        PlayerStats.database.dbUpdate("megawalls_stats", new KeyValue("coins", this.coins), new KeyValue("uuid", this.gamePlayer.getUuid().toString()));
    }
    
    public void takeCoins(final int amount) {
        if (this.coins - amount < 0) {
            return;
        }
        this.coins -= amount;
        PlayerStats.database.dbUpdate("megawalls_stats", new KeyValue("coins", this.coins), new KeyValue("uuid", this.gamePlayer.getUuid().toString()));
    }
    
    public void giveMythicDust(final int amount) {
        this.mythicDust += amount;
        PlayerStats.database.dbUpdate("megawalls_stats", new KeyValue("mythicDust", this.mythicDust), new KeyValue("uuid", this.gamePlayer.getUuid().toString()));
    }
    
    public void takeMythicDust(final int amount) {
        if (this.mythicDust - amount < 0) {
            return;
        }
        this.mythicDust -= amount;
        PlayerStats.database.dbUpdate("megawalls_stats", new KeyValue("mythicDust", this.mythicDust), new KeyValue("uuid", this.gamePlayer.getUuid().toString()));
    }

    
    public KitStatsContainer getKitStats(final Classes classes) {
        return this.kitStatsMap.getOrDefault(classes, null);
    }
    
    public List<Classes> unlockedClasses() {
        final List<Classes> list = new ArrayList<Classes>();
        for (final Map.Entry<Classes, KitStatsContainer> entry : this.kitStatsMap.entrySet()) {
            if (this.isUnlocked(entry.getKey())) {
                list.add(entry.getKey());
            }
        }
        return list;
    }
    
    public List<Classes> unlockedNormalClasses() {
        final List<Classes> list = new ArrayList<Classes>();
        for (final Classes classes : ClassesManager.getNormalClasses()) {
            if (this.isUnlocked(classes)) {
                list.add(classes);
            }
        }
        return list;
    }
    
    public List<Classes> unlockedMythicClasses() {
        final List<Classes> list = new ArrayList<Classes>();
        for (final Classes classes : ClassesManager.getMythicClasses()) {
            if (this.isUnlocked(classes)) {
                list.add(classes);
            }
        }
        return list;
    }
    
    public boolean isUnlocked(final Classes classes) {
        return this.kitStatsMap.get(classes).getLevel() >= 1;
    }
    
    public KitStatsContainer usuallyUsedClasses() {
        KitStatsContainer kitStats = null;
        for (final Map.Entry<Classes, KitStatsContainer> entry : this.kitStatsMap.entrySet()) {
            if (kitStats == null) {
                kitStats = entry.getValue();
            }
            else {
                if (entry.getValue().getPlayTime() <= kitStats.getPlayTime()) {
                    continue;
                }
                kitStats = entry.getValue();
            }
        }
        return kitStats;
    }
    
    public List<Classes> maxedClasses() {
        final List<Classes> list = new ArrayList<Classes>();
        for (final Classes classes : this.unlockedClasses()) {
            if (this.kitStatsMap.get(classes).isMaxed()) {
                list.add(classes);
            }
        }
        return list;
    }
    
    public int masterClasses() {
        int i = 0;
        final List<Classes> unlocked = this.unlockedClasses();
        for (final Classes classes : unlocked) {
            i += this.kitStatsMap.get(classes).getLevel();
        }
        return i - unlocked.size();
    }
    

    
    public GamePlayer getGamePlayer() {
        return this.gamePlayer;
    }
    
    public int getKills() {
        return this.kills;
    }
    
    public int getFinalKills() {
        return this.finalKills;
    }
    
    public int getWins() {
        return this.wins;
    }
    
    public int getGames() {
        return this.games;
    }
    
    public int getCoins() {
        return this.coins;
    }
    
    public int getMythicDust() {
        return this.mythicDust;
    }
    
    public EffectStatsContainer getEffectStats() {
        return this.effectStats;
    }
    

    
    public Map<Classes, KitStatsContainer> getKitStatsMap() {
        return this.kitStatsMap;
    }
    
    public Classes getCacheSelected() {
        return this.cacheSelected;
    }
    
    public void setCacheSelected(final Classes cacheSelected) {
        this.cacheSelected = cacheSelected;
    }
    
    static {
        PlayerStats.statsMap = new HashMap<GamePlayer, PlayerStats>();
        PlayerStats.database = MegaWalls.getInstance().getDataBase();
        PlayerStats.game = MegaWalls.getInstance().getGame();
        PlayerStats.gson = new Gson();
    }
}
